#ifndef __EIGENSOLVER_H__
#define __EIGENSOLVER_H__

#include "matvec.h"
#include "multilevel.h"

typedef struct EIGENSOLVER_
{
    // 求解器类型
    SOLVERTYPE solvertype;
    // 设置(√改动)
    INT nev;
    DOUBLE tol; 
    // 一些可能需要的结果(x改动)
    INT calltimes;
    // 数据
    MATRIX *A;
    MATRIX *B;
    DOUBLE *evals;
    VECTORS *evecs;
    MULTILEVEL *multilevel;
    bool alreadysetup;
    // 实现
    void *ops;
    void *data;
} EIGENSOLVER;

typedef struct EIGENSOLVER_OPS_
{
    void (*setup)(EIGENSOLVER *);
    void (*solve)(EIGENSOLVER *);
    void (*destory)(EIGENSOLVER *);
} EIGENSOLVER_OPS;

void EigenSolverCreate(EIGENSOLVER **solver, SOLVERTYPE type);
void EigenSolverSetType(EIGENSOLVER *solver, SOLVERTYPE type);
void EigenSolverSolve(EIGENSOLVER *solver, MATRIX *A, MATRIX *B, DOUBLE *eval, VECTORS *evec, INT num);
void EigenSolverDestroy(EIGENSOLVER **solver);

void EigenSolverMultiLevelSetUp(EIGENSOLVER *solver, MULTILEVEL *multilevel, INT nev);
void EigenSolverMultiLevelSolve(EIGENSOLVER *solver, MULTILEVEL *multilevel, DOUBLE *eval, VECTORS *evec, INT num);

#if defined(SLEPC_USE)
void EigenSolverCreate_SLEPc_KrylovSchur(EIGENSOLVER *solver);
#endif

#if defined(PASE_USE)
void EigenSolverCreate_GCGE(EIGENSOLVER *solver);
void EigenSolverCreate_PASE(EIGENSOLVER *solver);
void EigenSolverSetPASENev(EIGENSOLVER *solver, int nev);
void EigenSolverSetPASEInitialSolution(EIGENSOLVER *solver, int level, VECTORS *solution);
// 这个函数的区别是返回的不再是num个，而是会算上重根部分个，所以特征值和特征向量也会在这个函数内进行空间的分配
void EigenSolverGCGESolve(EIGENSOLVER *solver, MATRIX *A, MATRIX *B, DOUBLE **eval, VECTORS **evec, INT *num);
void EigenSolverPASESolve(EIGENSOLVER *solver, MATRIX *A, MATRIX *B, DOUBLE **eval, VECTORS **evec, INT *num);
void EigenSolverGetPASEPreconditioner(EIGENSOLVER *solver, void **A_preconditioner, void **B_preconditioner);
void EigenSolverSetPASEPreconditioner(EIGENSOLVER *solver, int coarse_level, void *A_preconditioner, void *B_preconditioner);
#endif


#endif